#ifndef _SENDSTRATEGY_H_
#define _SENDSTRATEGY_H_

#include "OSHeaders.h"

#include <string>
#include <map>
#include "RtpPacket.h"

/*
 *	Single thread SAFE ONLY! NOT use it in Multi-thread
 */
class CSendStrategy
{
public:
	enum STRATEGY_MODE { SM_ALL, SM_KEYFRAME};
	enum CODEC_TYPE { CT_MPEG4, CT_H264, CT_AUDIO, CT_UNKNOWN };
	enum STREAM_TYPE { ST_VIDEO, ST_AUDIO, ST_UNKOWN};

	struct SStreamInfo
	{
		UInt32		TrackID;
		STREAM_TYPE	StreamType;
		CODEC_TYPE	CodecType;

		//keyframe judge related
		UInt16		LastSeqNo;
		UInt32		LastTimeStamp;
		Bool		LastMarkBit;
		FRAME_TYPE	FrameType;
	};
	typedef std::map<UInt32, SStreamInfo>		StreamInfoMap;
	typedef StreamInfoMap::iterator		StreamInfoIterator;

protected:
	typedef Int32	STRATEGY_STATUS;
	enum { SS_ALL = 0, SS_KEYFRAME = 1, SS_AUDIO = 2};

public:
	CSendStrategy();
	~CSendStrategy();

public:
	void	Initialize(const std::string &strSDP, STRATEGY_MODE vMode = SM_KEYFRAME);

	/*
	 *	Initialize internal vars. Call this when seek/play
	 */
	void	ReStartStrategy(UInt32 vWindowSize = 100);

	/*
	 *	Decide if the packet is need to send
	 *	NOTE: make sure the packet is ordered
	 *	INPUT:
	 *		vType: if is PT_UNKOWN, auto detecte the payload type
	 */
	Bool	IsNeedSend(UInt32 vTrackID, const char *pData, UInt32 vLen, FRAME_TYPE vType = FT_UNKOWN);

	/*
	 * Set Send rate so that SendStrategy can decide to change strategy
	 * INPUT:
	 *		vRate: millesimal(1/1000)
	 */
	void	SetSentRate(UInt32 vRate);

	void	StatisticSendResult(Bool vSucc, UInt32 vLen);

	void	GetFrameType(UInt32 vTrackID, const char *pData, UInt32 vLen, FRAME_TYPE &vType);

	void	StartFrameTypeDetect();
	
protected:
	/*
	 *	Strategy mode control
	 *	if mode changed, return TRUE, else FALSE
	 */
	Bool	Schedule();

	/*
	 *	Only for video
	 */
	void	DetectFrameType(const char *pData, UInt32 vLen, SStreamInfo *pInfo, FRAME_TYPE &outType);

protected:
	StreamInfoMap		m_StreamInfos;

	STRATEGY_STATUS		m_Status;
	Bool				m_StatusChanged;

	STRATEGY_MODE		m_Mode;

	UInt32		m_CurSentRate;

	//statistic
	UInt32		m_WindowSize;
	UInt32		m_CurCount;
	UInt32		m_CurSucc;
	Int64		m_LastTime;

	UInt32		m_CurTotalLen;
	UInt32		m_CurSuccLen;
	UInt32		m_BetterByteRate;
	UInt32		m_CurByteRate;

	enum {KT_ALL = 5000, KT_KEYFRAME = KT_ALL * 3, KT_AUDIO = KT_KEYFRAME * 2};
};

/*
 *	Strategy mode 
 *		SM_ALL ---> SM_KEYFRAME ---> SM_AUDIO
 *			   <---				<---
 */
#endif	//_SENDSTRATEGY_H_